class Bluetooth {
	// 构造函数
	constructor() {
		this.isOpenBle = false;
		this.isStop = false;
		this.deviceList = [];
		this.deviceId = "";
		this.serviceId = "";
		this.readId = "";
		this.writeId = "";
		this.notifyId = "";
		this.indicateId = "";
		this.valueChangeData = {};
	}
	// 弹出框封装
	showToast(title) {
		uni.showToast({
			title: title,
			icon: 'none',
			'duration': 2000
		});
	}
	// 判断初始化蓝牙状态
	toast(code, errMsg) {
		switch (code) {
			case 10000:
				this.showToast('未初始化蓝牙适配器');
				break;
			case 10001:
				this.showToast('请打开蓝牙');
				break;
			case 10002:
				this.showToast('没有找到指定设备');
				break;
			case 10003:
				this.showToast('连接失败');
				break;
			case 10004:
				this.showToast('没有找到指定服务');
				break;
			case 10005:
				this.showToast('没有找到指定特征值');
				break;
			case 10006:
				this.showToast('当前连接已断开');
				break;
			case 10007:
				this.showToast('当前特征值不支持此操作');
				break;
			case 10008:
				this.showToast('其余所有系统上报的异常');
				break;
			case 10009:
				this.showToast('Android 系统特有，系统版本低于 4.3 不支持 BLE');
				break;
			default:
				this.showToast(errMsg);
		}
	}
	// 初始化蓝牙模块
	openBluetoothAdapter(callback) {
		uni.openBluetoothAdapter({
			success: res => {
				console.log('初始化>>>res', res)
				this.isOpenBle = true;
				this.startBluetoothDevicesDiscovery()
				if (typeof callback == "function")
					this.onBluetoothDeviceFound(callback);
			},
			fail: err => {
				console.log('初始化>>>err', err)
				this.toast(err.errCode);
			}
		});
	}
	// 关闭蓝牙模块
	closeBluetoothAdapter(callback) {
		return new Promise((resolve, reject) => {
			uni.closeBluetoothAdapter({
				success: res => {
					console.log(res)
					if (typeof callback == "function")
						callback();
				}
			});
		});
	}
	// 监听蓝牙适配器状态变化事件
	onBluetoothAdapterStateChange(callback) {
		uni.onBluetoothAdapterStateChange(res => {
			console.log('监听蓝牙适配器状态变化事件', res);
			if (!res.available) {
				this.isOpenBle = false
			}
			if (typeof callback == "function")
				callback(res);
		});
	}
	// 获取本机蓝牙适配器状态
	getBluetoothAdapterState() {
		let self = this;
		return new Promise((resolve, reject) => {
			uni.getBluetoothAdapterState({
				success: res => {
					console.log(JSON.stringify(res));
					resolve(res);
				},
				fail: err => {
					console.log('获取本机蓝牙适配器状态失败', err)
					self.toast(err.errCode);
					reject(err);
				}
			});
		});
	}
	// 搜索蓝牙设备
	startBluetoothDevicesDiscovery() {
		let self = this;
		return new Promise((resolve, reject) => {
			setTimeout(() => {
				if (!self.isOpenBle) {
					return;
				}
				uni.startBluetoothDevicesDiscovery({
					success: res => {
						resolve(res)
					},
					fail: err => {
						console.log('搜索设备失败', err)
						self.toast(err.errCode);
						reject(err);
					}
				})
			}, 300);
		});
	}
	// 停止搜索蓝牙设备
	stopBluetoothDevicesDiscovery() {
		uni.stopBluetoothDevicesDiscovery({
			success: res => {
				console.log('停止搜索蓝牙设备成功', res)
			},
			fail: err => {
				console.log('停止搜索蓝牙设备失败', err)
				this.toast(err.errCode);
			},
		})
	}
	// 发现外围设备
	onBluetoothDeviceFound(callback) {
		console.log('发现外围设备')
		// 侦听发现的设备
		uni.onBluetoothDeviceFound(devices => {
			console.log('监听寻找到新设备的事件');
			this.getBluetoothDevices(callback);
		});
	}
	// 获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
	getBluetoothDevices(callback) {
		uni.getBluetoothDevices({
			success: res => {
				this.deviceList = res.devices;
				callback();
			},
			fail: err => {
				console.log('获取蓝牙设备失败', err);
				this.toast(err.errCode);
			}
		});
	}
	//获取蓝牙设备所有服务(service)
	getBLEDeviceServices(callback) {
		let _serviceList = [];
		let deviceId = this.deviceId;
		let self = this;
		setTimeout(() => {
			//解决app不能得到服务的bug，500-1000
			uni.getBLEDeviceServices({
				deviceId,
				success: res => {
					console.log('getBLEDeviceServices success:', res)
					for (let service of res.services) {
						if (service.isPrimary) {
							_serviceList.push(service);
						}
					}
					// console.log("_serviceList: " + JSON.stringify(_serviceList));
					if (typeof callback == "function") callback(_serviceList)
				},
				fail: err => {
					console.log('getBLEDeviceServices fail:', err)
				},
				complete: res => {}
			});
		}, 500);
	}
	//获取蓝牙设备某个服务中所有特征值(characteristic)
	getBLEDeviceCharacteristics(serviceId) {
		let deviceId = this.deviceId;
		this.serviceId = serviceId;

		let self = this;
		let result = {
			readId: '',
			writeId: '',
			notifyId: '',
			indicateId: ''
		};
		return new Promise((resolve, reject) => {
			uni.getBLEDeviceCharacteristics({
				deviceId,
				serviceId,
				success: res => {
					console.log('getBLEDeviceCharacteristics success:', res)
					for (let _obj of res.characteristics) {
						//获取readId
						if (_obj.properties.read && !result.readId) {
							result.readId = _obj.uuid;
						}
						//获取writeId
						if (_obj.properties.write && !result.writeId) {
							result.writeId = _obj.uuid;
						}
						//获取notifyId
						if (_obj.properties.notify && !result.notifyId) {
							result.notifyId = _obj.uuid;
						}
						//获取indicateId
						if (_obj.properties.indicate && !result.indicateId) {
							result.indicateId = _obj.uuid;
						}
					}
					self = {
						...self,
						...result
					}
					resolve(result)
				},
				fail: err => {
					console.log("getBLEDeviceCharacteristics fail：", err);
					reject(err);
				}
			})
		});
	}
	// 连接低功耗蓝牙
	createBLEConnection(deviceId, callback) {
		let self = this;
		this.deviceId = deviceId;
		this.isStop = false;

		uni.createBLEConnection({
			deviceId,
			success: res => {
				if (typeof callback == "function") callback();
			},
			fail: err => {
				console.log('设备连接失败：', err)
				this.toast(err.errCode)
			},
		})
	}
	// 断开与低功耗蓝牙设备的连接
	closeBLEConnection(callback) {
		let deviceId = this.deviceId;
		this.isStop = true;
		uni.closeBLEConnection({
			deviceId,
			success(res) {
				console.log(res)
				if (typeof callback == "function")
					callback();
			}
		})
	}
	// 监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接，设备丢失，连接异常断开等等
	onBLEConnectionStateChange(callback) {
		uni.onBLEConnectionStateChange(res => {
			// 该方法回调中可以用于处理连接意外断开等异常情况
			console.log(`蓝牙连接状态 -------------------------->`, JSON.stringify(res));
			if (!res.connected) {
				if (this.isStop) return;
				console.log('断开低功耗蓝牙成功');
				this.valueChangeData = {};
				this.showToast('已经断开当前蓝牙连接');
				if (typeof callback == "function") callback();
			}
		});
	}
	// 监听低功耗蓝牙设备的特征值变化事件。必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
	onBLECharacteristicValueChange() {
		// 必须在这里的回调才能获取
		uni.onBLECharacteristicValueChange(characteristic => {
			console.log('监听低功耗蓝牙设备的特征值变化事件成功');
			console.log(JSON.stringify(characteristic));
			this.valueChangeData = characteristic;
		});
	}
	// 读取低功耗蓝牙设备的特征值的二进制数据值。注意：必须设备的特征值支持 read 才可以成功调用
	readBLECharacteristicValue() {
		let deviceId = this.deviceId;
		let serviceId = this.serviceId;
		let characteristicId = this.readId;
		console.log(deviceId);
		console.log(serviceId);
		console.log(characteristicId);
		uni.readBLECharacteristicValue({
			deviceId,
			serviceId,
			characteristicId,
			success: res => {
				console.log('读取设备数据值成功');
				console.log(JSON.stringify(res));
				this.notifyBLECharacteristicValueChange();
			},
			fail(err) {
				console.log('读取设备数据值失败', err);
				this.toast(err.errCode);
			}
		});
		this.onBLECharacteristicValueChange();
	}
	// 向低功耗蓝牙设备特征值中写入二进制数据
	writeBLECharacteristicValue(buffer, deviceId, serviceId, characteristicId) {
		let self = this;
		deviceId = this.deviceId || deviceId
		serviceId = this.serviceId || serviceId
		characteristicId = this.characteristicId || characteristicId

		console.log(deviceId, serviceId, characteristicId)

		let datalen = 20;
		if (uni.getSystemInfoSync().platform == 'ios') {
			datalen = 180;
		}
		let pos = 0;
		let fail_count = 0;
		let bytes = buffer.byteLength;
		console.log("bytes", bytes)

		while (bytes > 0) {
			let tmpBuffer;
			if (bytes > datalen) {
				tmpBuffer = buffer.slice(pos, pos + datalen);
				pos += datalen;
				bytes -= datalen;
				uni.writeBLECharacteristicValue({
					deviceId: deviceId,
					serviceId: serviceId,
					characteristicId: characteristicId,
					value: tmpBuffer,
					fail: function(err) {
						console.log('writeBLECharacteristicValue fail', err)
						self.toast(err.errCode);
						fail_count++;
					}
				})
			} else {
				tmpBuffer = buffer.slice(pos, pos + bytes);
				pos += bytes;
				bytes -= bytes;
				uni.writeBLECharacteristicValue({
					deviceId: deviceId,
					serviceId: serviceId,
					characteristicId: characteristicId,
					value: tmpBuffer,
					fail: function(err) {
						console.log('writeBLECharacteristicValue fail', err)
						self.toast(err.errCode);
						fail_count++;
					}
				})
			}
		}
		if (!fail_count) {
			return {
				success: true
			}
		} else {
			return {
				success: false,
				msg: '打印失败'
			}
		}
	}
	// 启用低功耗蓝牙设备特征值变化时的 notify 功能
	notifyBLECharacteristicValueChange() {
		let deviceId = this.deviceId;
		let serviceId = this.serviceId;
		let characteristicId = this.notifyId;

		uni.notifyBLECharacteristicValueChange({
			state: true, // 启用 notify 功能
			deviceId,
			serviceId,
			characteristicId,
			success: res => {
				uni.onBLECharacteristicValueChange((res) => {
					console.log('特征值变化：', res)
				});
			},
			fail: err => {
				console.log('notifyBLECharacteristicValueChange 失败:' + err.errMsg);
			}
		});
	}
	//若APP在之前已有搜索过某个蓝牙设备，并成功建立连接，可直接传入之前搜索获取的 deviceId 直接尝试连接该设备，无需进行搜索操作。
	reconnect() {
		(async () => {
			try {
				this.deviceId = this.deviceId || uni.getStorageSync("deviceId");
				this.serviceId = this.serviceId || uni.getStorageSync("serviceId");

				let result1 = await this.createBLEConnection();
				console.log("createBLEConnection: " + JSON.stringify(result1));

				let result2 = await this.getBLEDeviceServices();
				console.log("getBLEDeviceServices: " + JSON.stringify(result2));

				let result3 = await this.getBLEDeviceCharacteristics();
				console.log("getBLEDeviceCharacteristics: " + JSON.stringify(result3));
			} catch (err) {
				console.log("err: " + JSON.stringify(err));
			}

		})();
	}
}

export default Bluetooth;
